package chartadvancedscatterlive;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.SequentialTransition;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.ScatterChart;
import javafx.scene.chart.XYChart;
import javafx.stage.Stage;
import javafx.util.Duration;

/**
 * A live scatter chart.
 */
public class ChartAdvancedScatterLive extends Application {

    private ScatterChart.Series<Number,Number> series;
    private double nextX = 0;
    private SequentialTransition animation;

    private void init(Stage primaryStage) {
        Group root = new Group();
        primaryStage.setScene(new Scene(root));
        root.getChildren().add(createChart());
        // create animation
        Timeline timeline1 = new Timeline();
        timeline1.getKeyFrames().add(
            new KeyFrame(Duration.millis(20), actionEvent -> {
                series.getData().add(new XYChart.Data<>(
                        nextX,
                        Math.sin(Math.toRadians(nextX)) * 100
                ));
                nextX += 10;
            })
        );
        timeline1.setCycleCount(200);
        Timeline timeline2 = new Timeline();
        timeline2.getKeyFrames().add(
                new KeyFrame(Duration.millis(50), actionEvent -> {
                    series.getData().add(new XYChart.Data<>(
                            nextX,
                            Math.sin(Math.toRadians(nextX)) * 100
                    ));
                    if (series.getData().size() > 54) series.getData().remove(0);
                    nextX += 10;
                })
        );
        timeline2.setCycleCount(Animation.INDEFINITE);
        animation = new SequentialTransition();
        animation.getChildren().addAll(timeline1,timeline2);
    }

    private ScatterChart<Number, Number> createChart() {
        final NumberAxis xAxis = new NumberAxis();
        xAxis.setForceZeroInRange(false);
        final NumberAxis yAxis = new NumberAxis(-100,100,10);
        final ScatterChart<Number,Number> sc = new ScatterChart<>(xAxis, yAxis);
        // setup chart
        sc.setId("liveScatterChart");
        sc.setTitle("Animated Sine Wave ScatterChart");
        xAxis.setLabel("X Axis");
        xAxis.setAnimated(false);
        yAxis.setLabel("Y Axis");
        yAxis.setAutoRanging(false);
        // add starting data
        series = new ScatterChart.Series<>();
        series.setName("Sine Wave");
        series.getData().add(new ScatterChart.Data<>(5d, 5d));
        sc.getData().add(series);
        return sc;
    }

    public void play() {
        animation.play();
    }

    @Override
    public void stop() {
        animation.pause();
    }    

    @Override
    public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
        play();
    }

    /**
     * The main() method is ignored in correctly deployed JavaFX 
     * application. main() serves only as fallback in case the 
     * application can not be launched through deployment artifacts,
     * e.g., in IDEs with limited FX support. NetBeans ignores main().
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}
